#include "Log.h"
#include "timewheel.h"
#include <EventLoop.h>
#include <asm-generic/errno-base.h>
#include <asm-generic/errno.h>
#include <cerrno>
#include <cstdlib>
#include <functional>
#include <mutex>
#include <stdexcept>
#include <thread>
#include <unistd.h>
#include <vector>

namespace muduo{
    int EventLoop::CreateEventFd(){
        // count为初始值，EFD_CLOEXEC禁止线程复制，EFD_NONBLOCK非阻塞
        int efd = eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);
        if(efd < 0){
            errorlog<<"eventfd create error";
            abort();
        }
        return efd;
    }
    void EventLoop::RunAllTask(){
        // 如果对任务队列加锁后逐一执行任务，则使代码长时间在此阻塞，所以使用置换方法交换出任务，提高效率
        std::vector<functor> newtaskqueue;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _taskqueue.swap(newtaskqueue);
        }
        for(auto func:newtaskqueue){
            func();
        }
    }
    void EventLoop::ReadEventFd(){
        // 必须是64位的顺利读取
        uint64_t res=0;
        int ret = read(_event_fd, &res, sizeof(res));
        if(ret < 0){
            if(errno & EINTR || errno & EAGAIN){
                return;
            }
            errorlog << "read eventfd error" ;
            abort();
        }
    }
    int EventLoop::Get_event_fd(){return _event_fd;}
    void EventLoop::WeakUpEventFd(){
        uint64_t res=0;
        int ret = write(_event_fd, &res, sizeof(res));
        if(ret < 0){
            if(errno & EINTR || errno & EAGAIN){
                return;
            }
            errorlog << "read eventfd error" ;
            abort();
        }
    }
    EventLoop::EventLoop():_event_fd(CreateEventFd()),_thread_id(std::this_thread::get_id())\
                                        ,_event_channel(new Channel(this,_event_fd)),_timewheel(new TimerWheel(this) )
    {
        // _timewheel = new TimerWheel(this);
        // 给_event_fd绑定回调以及添加读事件监控
        _event_channel->Set_read_callback(std::bind(&EventLoop::ReadEventFd,this));
        _event_channel->EnableRead();
    }
    void EventLoop::start(){
        while(true){
            // 三步走:获得就绪事件，处理就绪事件，执行任务队列中的任务
            // 1.
            std::vector<Channel *> evs;
            // 有的情况下，epoll.wait阻塞等待IO事件的发生，但是有可能其它的线程向任务队列中添加了数据
            // 但是因为有阻塞，所以一直无法执行任务队列中的任务，这时就需要_evtnt_fd唤醒阻塞，先执行
            // 任务队列中的任务，执行完毕之后，可以再阻塞监听
            _poller.ActiveEvent(&evs);
            // 2.
            for(auto ev:evs){
                ev->HanderEvents();
                // ev->SetEvents(0);
            }
            // 3.
            RunAllTask();
        }
    }
    bool EventLoop::IsCurThread(){
        return std::this_thread::get_id() == _thread_id;
    }
    void EventLoop::PushTask(const functor& func){
        // 因为可能会有多个线程同时向任务队列添加数据，所以需要加锁
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _taskqueue.push_back(func);
        }
        // 唤醒没有事件就绪而阻塞epoll，向_event_fd 写数据唤醒阻塞的epoll
        WeakUpEventFd();
    }
    void EventLoop::RunLoop(const functor& cb){
        int flag= IsCurThread();
        if(flag == true){
            return cb();          
        }
        PushTask(cb);
    }
    void EventLoop::UpdateEvent(Channel *channel){_poller.UpdateEvent(channel);}
    void EventLoop::RemoveEvent(Channel *channel){_poller.RemoveEvent(channel);}
    void EventLoop::AddTimerTask(uint64_t id,uint32_t delay,const Task_func& task_cb){
        _timewheel->AddTimerTask(id, delay, task_cb);
    }
        // 更新/延迟定时任务
    void EventLoop::TimerRefresh(uint64_t id){
        _timewheel->TimerRefresh(id);
    }   
    void EventLoop::TimerCancel(uint64_t id){
        _timewheel->TimerCancel(id);
    }
    bool EventLoop::HasTimer(uint64_t id){
        return _timewheel->HasTimer(id);
    }

}